#include "stdafx.h"
#if LIT_BOOST_SUPPORT
#include <LitFilePath.h>
#include <LitFileSystem.h>

LIT_API std::ostream& operator<<( std::ostream& strm, const Lit::FilePath &str ){ strm << str.str(); return strm; }

namespace Lit
{
	FilePath::FilePath( ){}
	FilePath::FilePath( const String::char_type* path ){ p=path; sanitise(); }
	FilePath::FilePath( const String &path ){ p=path; sanitise(); }
	FilePath::FilePath( const FilePath& path ){ p = path.p; sanitise(); }
	FilePath::~FilePath(){}
		
	FilePath::operator String(){ return p; }

	bool FilePath::isFile() const{ return boost::filesystem::is_regular_file(p.data()); }
	bool FilePath::isDirectory() const{ return boost::filesystem::is_directory(p.data()); }
	bool FilePath::isSymLink() const{ return boost::filesystem::is_symlink(p.data()); }
		
	bool FilePath::empty() const{ return p.empty(); }
	String FilePath::str() const{ return p; }

	FilePathVector FilePath::listDirectory( FilePathType filter_type, const FilePath &path_, bool recurse_into_subdirs, FilePathVector * recurse_vec ) const
	{
		FilePathVector v;
		if( !recurse_vec ) recurse_vec = &v;

		FilePath path(path_.str().empty()?p:path_);
		if( !boost::filesystem::is_directory(path.str().data()) ) return v;
		if( boost::filesystem::exists( path.str().data( ) ) )
		{
			boost::filesystem::directory_iterator end ;
			for( boost::filesystem::directory_iterator iter(p.data()) ; iter != end ; ++iter )
			{
				bool ok_filter = false;
				String dir(boost::filesystem::path((*iter)).string().c_str());
				switch( filter_type )
				{
				case FPT_FILE: if( boost::filesystem::is_regular_file(dir.data()) ){ ok_filter = true; recurse_vec->push_back( dir.data() ); } break;
				case FPT_SYMLINK: if( boost::filesystem::is_symlink(dir.data()) ){ ok_filter = true;  recurse_vec->push_back( dir.data() ); } break;
				case FPT_DIRECTORY: if( boost::filesystem::is_directory(dir.data()) ){ ok_filter = true;  recurse_vec->push_back( dir.data() ); } break;
				case FPT_INVALID: 
				default: 
					ok_filter = true;
					recurse_vec->push_back( dir );
				};
				if ( boost::filesystem::is_directory( *iter ) )
				{
					if( recurse_into_subdirs ) 
						listDirectory( filter_type, dir, recurse_into_subdirs, recurse_vec) ;
				}
			}
		}
		return v;
	}
		
	FilePathType FilePath::getType() const
	{
		if( !exists() ) return FPT_INVALID;
		if( isDirectory() ) return FPT_DIRECTORY;
		else if( isSymLink() ) return FPT_SYMLINK;
		return FPT_FILE;
	}
	size_t FilePath::size() const{
		return p.size();
	}
	bool FilePath::hasTrailingSlash() const{
		if( p.empty() ) return false;
		return (p.at(p.size()-1) == '/' || p.at(p.size()-1) == '\\');
	}
	void FilePath::setTrailingSlash( bool state ){
		if( p.empty() ) return;
		if( state )
		{
			if( hasTrailingSlash() )
				return;
			else
				p += '/';
		}
		else {
			if( !hasTrailingSlash() )
				return;
			else
				p.erase( p.size()-1 );
		}
	}
	bool FilePath::startsWith( const FilePath & path ) const
	{
		if( path.size() > p.size() ) return false;
		return p.substr( 0, path.size()-1 ) == path.str();
	}
	bool FilePath::endsWith( const FilePath & path ) const
	{
		if( path.size() > p.size() ) return false;
		return p.substr( p.size()-path.size(), path.size()-1 ) == path.str();
	}
	bool FilePath::contains( const FilePath & path ) const
	{
		String lp( p.toLower() );
		String lp2( path.str().toLower() );

		return (p.find(path.str())!=String::npos);
	}
	String FilePath::removeIfFound( const FilePath & rem_path ) const
	{
		size_t count = rem_path.str().size();
		size_t pos = p.find(rem_path.str());
		if( pos!=String::npos )
		{
			return p.substr( (pos+1), count-(pos+1) );
		}
		return p;
	}
	String FilePath::extension() const{ 
		String fname(fileName());
		size_t p = fname.rfind('.');
		if( p == String::npos )
			return "";
		return fname.substr( p+1, fname.size() - (p+1) );
	};
	String FilePath::fileName( bool with_ext ) const{ 
		String n = Lit::FileSystem::fileName(p); 
		
		if( with_ext ) return n;

		size_t pos = n.rfind('.');
		if( pos == String::npos ) return n;
		n = n.substr(0, pos);
		return n;
	}
	String FilePath::dirName() const{ return Lit::FileSystem::dirName(p); }
	
	std::ostream& operator<<( std::ostream& strm, const FilePath& p )
	{
		strm << p.p.data();
		return strm;
	}

	FilePath FilePath::parent() const{ return FilePath(boost::filesystem::path(p.data()).parent_path().string().c_str()); }
	bool FilePath::exists() const{ return boost::filesystem::exists( p.data() );}
	void FilePath::sanitise(){p=boost::filesystem::path(p.data()).string().c_str();}
	void FilePath::make(){ Lit::FileSystem::createDirectories(p.data()); }
	
	FilePath& FilePath::operator = ( const FilePath& rk ){p=rk.p; return *this;}
	FilePath& FilePath::operator = ( const String& rk ){p=rk; return *this;}

	FilePath FilePath::operator + ( const FilePath& rk ) const{return FilePath(p+rk.p);}
	FilePath& FilePath::operator += ( const FilePath& rk ){p+=rk.p; return *this;}
	FilePath FilePath::operator + ( const String& rk ) const{return FilePath(p+rk);}
	FilePath& FilePath::operator += ( const String& rk ){p+=rk; return *this;}
	FilePath FilePath::operator + ( const char * str ) const{return FilePath(p+String(str));}
	FilePath& FilePath::operator += ( const char * str ){p+=String(str); return *this;}

};

#endif